package com.fastloan.common.excel;

import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.ss.usermodel.BorderStyle;
import org.apache.poi.ss.usermodel.FillPatternType;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.util.CellRangeAddress;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.IntStream;

/**
 * Created by gelon on 2017/10/18.
 */
public class ExcelUt {


    public static void outPut(HttpServletResponse response, String excelName, HSSFWorkbook wb) {
        OutputStream output = null;
        try {
            output = response.getOutputStream();
            response.reset();
            response.setHeader("Content-disposition", "attachment; filename=" + URLEncoder.encode(excelName, "UTF-8") + ".xls");
            response.setContentType("application/msexcel");
            response.setCharacterEncoding("UTF-8");
            wb.write(output);
            output.close();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (output != null) {
                try {
                    output.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

        }
    }

    public static void resPonse(HttpServletResponse response, String excelName, List<Sheet> sheets) {
        outPut(response, excelName, buildExcel(sheets));
    }


    public static HSSFWorkbook buildExcel(List<Sheet> sheets) {
        HSSFWorkbook wb = new HSSFWorkbook();
        Map<String, HSSFCellStyle> styleMap = new HashMap<>();
        IntStream.range(0, sheets.size()).forEach(idx -> buildSheet(wb, sheets.get(idx), styleMap));
        return wb;
    }

    private static void buildSheet(HSSFWorkbook wb, Sheet sheet, Map<String, HSSFCellStyle> styleMap) {
        HSSFSheet hssfSheet = wb.createSheet(sheet.name);
        sheet.treeSetSort.forEach(form -> push(hssfSheet, form, wb, styleMap));
    }

    private static void push(HSSFSheet hssfSheet, Form form, HSSFWorkbook wb, Map<String, HSSFCellStyle> styleMap) {
        HSSFRow row = findCreate(hssfSheet, form);
        HSSFCell cell = row.createCell(form.startColumn);
        autoSize(hssfSheet, form.startColumn, form.text);
        cell.setCellStyle(popStyle(form, styleMap, wb));
        if (form.endRow != null) {
            hssfSheet.addMergedRegion(new CellRangeAddress(form.startRow, form.endRow, form.startColumn, form.endColumn));
        }
        cell.setCellValue(form.text);
    }

    private static void autoSize(HSSFSheet hssfSheet, int columnNum, String text) {
        int length = text.getBytes().length * 2 * 256;
        length = length < 6000 ? length : 6000;
        if (hssfSheet.getColumnWidth(columnNum) < length) {
            hssfSheet.setColumnWidth(columnNum, length);
        }
    }


    private static HSSFCellStyle popStyle(Form form, Map<String, HSSFCellStyle> styleMap, HSSFWorkbook wb) {
        String styleKey = "" + form.bordenColor + form.backgroundColor + form.fontColor + form.fontSize + form.bold;
        HSSFCellStyle style = styleMap.get(styleKey);
        if (style == null) {
            style = wb.createCellStyle();
            if (form.bordenColor != null) {
                buildBorderStyle(form.bordenColor, style);
            }
            if (form.backgroundColor != null) {
                style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
                style.setFillForegroundColor(form.backgroundColor);
            }
            if (form.fontColor != null || form.fontSize != null) {
                style.setFont(buildFont(form, wb));
            }

            style.setAlignment(HorizontalAlignment.CENTER);
            styleMap.put(styleKey, style);
        }
        return style;
    }


    public static HSSFFont buildFont(Short fColor, Short fSize, HSSFWorkbook workbook) {
        HSSFFont font = workbook.createFont();
        if (fColor != null) {
            font.setColor(fColor);
        }
        if (fSize != null) {
            font.setFontHeightInPoints(fSize);
        }
        return font;
    }


    private static HSSFCellStyle buildBorderStyle(short color, HSSFCellStyle style) {
        style.setBorderBottom(BorderStyle.THIN);
        style.setBottomBorderColor(color);
        style.setBorderLeft(BorderStyle.THIN);
        style.setLeftBorderColor(color);
        style.setBorderRight(BorderStyle.THIN);
        style.setRightBorderColor(color);
        style.setBorderTop(BorderStyle.THIN);
        style.setTopBorderColor(color);
        return style;
    }

    private static HSSFRow findCreate(HSSFSheet hssfSheet, Form form) {
        HSSFRow row = hssfSheet.getRow(form.startRow);
        if (row == null) {
            row = hssfSheet.createRow(form.startRow);
        }
        return row;
    }


    public static HSSFFont buildFont(Form form, HSSFWorkbook workbook) {
        HSSFFont font = workbook.createFont();
        if (null != form.fontColor) {
            font.setColor(form.fontColor);
        }
        if (null != form.fontSize) {
            font.setFontHeightInPoints(form.fontSize);
        }
        font.setBold(form.bold);
        return font;
    }

}
